﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace Orm.Toolkit.Telerik.Windows.Controls.Animation
{
	/// <summary>
	/// Base class for dynamic control animations.
	/// </summary>
	/// <remarks>
	/// </remarks>
	public abstract class RadAnimation
	{
		internal static readonly double PixelsPerSecond = 500;

		/// <summary>
		/// Gets or sets the name of the animation.
		/// </summary>
		/// <remarks>
		///		<para>
		///			This property is used by the NamedAnimationSelector to identify the 
		///			correct animation to return. 
		///		</para>
		///		<para>
		///			It is not used outside the NamedAnimationSelector
		///		</para>
		/// </remarks>
		public string AnimationName
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the value for the SpeedRatio of the Storyboard generated by this animation.
		/// </summary>
		public double SpeedRatio
		{
			get;
			set;
		}

		/// <summary>
		/// When overridden in a derived class this method is called when the animation for an 
		/// instance of a control needs to be created.
		/// </summary>
		/// <param name="control">The control for which the animation is needed.</param>
		/// <returns>The newly created animation.</returns>
		public abstract Storyboard CreateAnimation(FrameworkElement control);

		/// <summary>
		///		When overridden in a derived class this method updates the animation
		///		before it is played.
		/// </summary>
		/// <param name="control">The control for which the animation needs to be updated.</param>
		/// <param name="storyboard">Storyboard that needs to be updated.</param>
		/// <param name="args">A set of arguments used for animation creation.</param>
		/// <remarks>
		///		<para>
        ///			Currently the method sets the <see cref="SpeedRatio"/> of the storyboard to
        ///			the global <strong>AnimationSpeedRatio</strong> if the local <see cref="SpeedRatio"/> is null.
        ///			If the local <see cref="SpeedRatio"/> value is set, it will be used.
		///		</para>
		/// </remarks>
		public virtual void UpdateAnimation(FrameworkElement control, Storyboard storyboard, params object[] args)
		{
			if (this.SpeedRatio != 0)
			{
				storyboard.SpeedRatio = this.SpeedRatio;
			}
			else
			{
				storyboard.SpeedRatio = AnimationManager.AnimationSpeedRatio;
			}
		}

		internal static double GetDurationSecondsForLength(double pixelsLength)
		{
			var duration = pixelsLength / (double)PixelsPerSecond;
			return Math.Max(duration, 0.2);
		}

		internal static FrameworkElement FindTarget(FrameworkElement control, string targetName)
		{
			if (String.IsNullOrEmpty(targetName))
			{
				return control;
			}
			else
			{
				if (VisualTreeHelper.GetChildrenCount(control) > 0)
				{
					var layoutRoot = VisualTreeHelper.GetChild(control, 0) as FrameworkElement;
					return layoutRoot.FindName(targetName) as FrameworkElement;
				}
			}
			return null;
		}
	}
}
